#pragma once
#include "thread.hpp"
#include <vector>
#include <queue>
#include "lockGuard.hpp"
#include <string>
#include "log.hpp"

const int g_thread_num = 5;
template<class T>
class ThreadPool
{
public:
    pthread_mutex_t* getmutex()
    {
        return &lock_;
    }
    bool isEmpty()
    {
        return task_queue_.empty();
    }
    void waitCond()
    {
        pthread_cond_wait(&cond_,&lock_);
    }
    T getTask()
    {
        T t = task_queue_.front();
        task_queue_.pop();
        return t;
    }
    ThreadPool(int thread_num = g_thread_num):num_(thread_num)
    {
        pthread_mutex_init(&lock_,nullptr);
        pthread_cond_init(&cond_,nullptr);
        for(int i = 0; i < num_ ; i++)
        {
            threads_.push_back(new Thread(i,routine,this));
        }
    }
    ThreadPool(const ThreadPool<T>& tp) = delete;
    ThreadPool<T> operator=(const ThreadPool<T>& tp) = delete; 
public:
    static ThreadPool<T>* GetThreadPool(int num = g_thread_num) 
    {
        if(thread_ptr_ == nullptr)
        {
            lockGuard lockguard(&mutex_);
            if(thread_ptr_ == nullptr)
            {
                thread_ptr_ = new ThreadPool<T>(num);
            }
        }
        return thread_ptr_;
    }
    ~ThreadPool()
    {
        for(auto &iter : threads_)
        {
            iter->join();
            delete iter;
        }
        pthread_mutex_destroy(&lock_);
        pthread_cond_destroy(&cond_);
    }
    static void* routine(void* args)//消费
    {
        ThreadData* td = (ThreadData*) args;
        ThreadPool<T>* tp = (ThreadPool<T>*)td->args_;
        
        while(true)
        {
            T task;
            {
                lockGuard lockguard(tp->getmutex());
                
                while(tp->isEmpty())
                {
                    tp->waitCond();
                }
                // 确认有数据可以消费
                task = tp->getTask();
            }
            task(td->name_.c_str());
        }
    }
    void run()
    {
        for(auto& iter:threads_)
        {
            iter->start(); 
            logMessage(NORMAL, "%s %s",iter->name().c_str(),"启动成功");
            //std::cout <<iter->name() << " 启动成功" << std::endl;
        }
    }
    void pushTask(const T& task)//
    {
        lockGuard lockguard(&lock_);
        task_queue_.push(task);
        pthread_cond_broadcast(&cond_);
    }
private:
    std::vector<Thread*> threads_;
    int num_;
    std::queue<T> task_queue_;

    pthread_mutex_t lock_;
    pthread_cond_t cond_;

    static ThreadPool<T>* thread_ptr_;
    static pthread_mutex_t mutex_;
};
template<typename T>
ThreadPool<T>* ThreadPool<T>::thread_ptr_ = nullptr;

template<typename T>
pthread_mutex_t ThreadPool<T>::mutex_ = PTHREAD_MUTEX_INITIALIZER;